local skynet = require "skynet"
local socket = require "socket"
local cluster = require "cluster"
local CMD = require "main_proto"
local CMDGAME = require "game_proto"
local Sraw = require "stable.raw"
Sraw.init()
local QueryStr = require("core").QueryStr

local bufferrw = require "buffrw"
local buffwrite = bufferrw.BuffWrite
local buffread  = bufferrw.BuffRead

local lobby = require "lobbysql"
local CEN = require "center_proto"
local PLATFORM_ID = tonumber(skynet.getenv('platform_type')) or 1 

local WATCHDOG
local client_fd
local client_addr = ""
local bReConnect = false
local authed   = false
local timeout  = 0

local login --= require "login"
local Manager 
local Self
local playerId
local playerList
local player
local Center_conn

local function send_package(fd, pack)
	local package = string.pack(">s2", pack)
	socket.write(fd, package)
end

local function SendData(addr,cmd,...)
    if math.floor(addr) > 0 then
        skynet.send(math.floor(addr),"lua",cmd,...)
    end
end

local function error_toClose()
    skynet.call(WATCHDOG, "lua", "close", client_fd)
end


local function request(smsg, sz)
    if sz < 4 then
        skynet.error("error close fd find  non-standard packet sz:"..sz)
        error_toClose()
        return nil
    end
    local BuffRead = buffread.new(smsg)
    local mcmd, scmd = BuffRead:proto()

    if not (mcmd == 303 and scmd == 1032) then
        skynet.error(" rev mcmd: ", mcmd, " scmd: ", scmd)
    end

    if mcmd == CMD.Main_ClientAndGameSvr_UserModle then  
        if scmd == CMD.Sub_ClientToGameSvr_UserModle_GateInfor then --客户端地址
            client_addr = string.unpack("z", smsg,  5)--= skynet.call(Manager, "lua", "OnUserGateInfor", smsg)
        elseif  scmd == CMD.Sub_ClientToGameSvr_UserModle_LoginReq then --登录
            local bFirstLogin = 0
            playerId, authed = skynet.call(Login, "lua", "OnUserLoginReq", smsg, Self,client_addr)
            if not authed then 
                CMD.disconnect()
            else
                player = Sraw.get(playerList,tostring(playerId))
            end
        elseif  scmd == CMD.Sub_ClientToGameSvr_UserModle_CreateAccountReq then --创建账号
            playerId, authed = skynet.call(Login, "lua", "OnUserCreateReq", smsg, Self,client_addr)
            if not authed then 
                CMD.disconnect()
            else
                player = Sraw.get(playerList,tostring(playerId))
            end
        elseif  scmd == CMD.Sub_ClientToGameSvr_UserModle_LogoutReq then --退出账号
            skynet.send(Login, "lua", "OnUserLogoutReq", smsg, Self,player)
        elseif scmd == CMD.Sub_ClientToGameSvr_UserModle_ZhanjiReq and authed then -- 读战绩
            lobby.ZhanjiReq(player)
        elseif scmd == CMD.Sub_ClientToGameSvr_UserModle_UserUpdateInfoReq then
            lobby.OnUserUpdateInfo(player)
        elseif scmd == CMD.Sub_ClientToGameSvr_UserModle_UserAuthedInfoReq then
            lobby.OnNetGetUserPhoneInformation(player)
        elseif scmd == CMD.Sub_ClientToGameSvr_UserModle_GetRewardReq then    --领取奖励
            lobby.OnGetRewardReq(smsg,player)
        end
    elseif  mcmd == CMD.Main_ClientAndGameSvr_LobbyModle then                           --大厅消息
        if scmd == CMD.Sub_ClientToGameSvr_LobbyModle_PreCreateRoomReq and authed then --预创建房间
            skynet.send(Manager, "lua", "OnNetMsgPreCreateAccountReq", smsg, playerId)
        elseif scmd == CMD.Sub_ClientToGameSvr_LobbyModle_CreateRoomReq and authed then --创建房间
            skynet.call(Manager, "lua", "OnNetMsgCreateRoomReq", smsg,playerId)
        elseif scmd == CMD.Sub_ClientToGameSvr_LobbyModle_PreEnterRoomReq and authed then --预进入房间
            skynet.send(Manager, "lua", "OnNetMsgPreEnterRoomReq", smsg, playerId)
        elseif scmd == CMD.Sub_ClientToGameSvr_LobbyModle_EnterRoomReq and authed then --进入房间 
            skynet.call(Manager, "lua", "OnNetMsgEnterRoomReq", smsg,playerId)
        elseif scmd == CMD.Sub_ClientToGameSvr_LobbyModle_ChangeJinBiReq then          --兑换老友豆
            lobby.ChangeJinBiReq(smsg,player)
        elseif scmd ==  CMD.Sub_ClientToGameSvr_LobbyModle_BuyDiamondReq then           --购买钻石 
            lobby.BuyDiamondReq(smsg,player)
        elseif scmd == CMD.Sub_ClientToGameSvr_LobbyModle_ReqExternCode then        --绑定推荐码
            lobby.InputExternReq(smsg,player)
        elseif scmd == CMD.Sub_ClientToGameSvr_LobbyModle_GetServerTimeReq then          --客户端获取服务器时间
            local msg = string.pack(">I2I2<i",
                CMD.Main_ClientAndGameSvr_LobbyModle,CMD.Sub_GameSvrToClient_LobbyModle_GetServerTimeResp,os.time())
            CMD.send_data(msg)
        end
    elseif mcmd == CMDGAME.Main_ClientAndGameSvr_TableModle and authed  then --房间消息
        if scmd == CMDGAME.Sub_ClientToGameSvr_TableModle_PingPong then --客户端的Ping消息
            local nID,nCheckTime,bFirstTimeOnEnterForGround = string.unpack("i4i4i1",smsg,5)
            local msg = string.pack(">I2>I2<i4i4i1",
                CMDGAME.Main_ClientAndGameSvr_TableModle, CMDGAME.Sub_GameSvrToClient_TableModle_PingPong,
                nID,nCheckTime,bFirstTimeOnEnterForGround
                )
            CMD.send_data(msg)
        elseif scmd == CMDGAME.Sub_ClientToGameSvr_TableModle_ReadyActionReq then -- 举手动作
            SendData(Sraw.get(player,"nRoomAddr"),"OnNetMsgReadyActionReq", smsg, player)
        elseif scmd == CMDGAME.Sub_ClientToGameSvr_TableModle_StandUpReq then -- 离开桌子
            SendData(Sraw.get(player,"nRoomAddr"),"OnNetMsgStandUpReq", player)
        elseif scmd == CMDGAME.Sub_ClientToGameSvr_TableModle_DoChoice then -- 解散选择
            SendData(Sraw.get(player,"nRoomAddr"), "OnNetMsgUserDoChoice", smsg, player)
        elseif scmd == CMDGAME.Sub_ClientToGameSvr_TableModle_GoOnGameReq  then -- 继续游戏
            SendData(Sraw.get(player,"nRoomAddr"),"OnNetMsgUserGoOnGameReq", player)
        elseif scmd == CMDGAME.Sub_ClientToGameSvr_TableModle_WantVoiceReq then --发送文字请求
            SendData(Sraw.get(player,"nRoomAddr"),"OnNetMsgUserWantVoiceReq",smsg,player)
        elseif scmd == CMDGAME.Sub_ClientToGameSvr_TableModle_WantFaceReq then --发送表情请求
            SendData(Sraw.get(player,"nRoomAddr"),"OnNetMsgUserWantFaceReq",smsg,player)
        elseif scmd == CMDGAME.Sub_ClientToGameSvr_TableModle_SendTxtReqs then    --发送自定义文字
            SendData(Sraw.get(player,"nRoomAddr"),"OnNetMsgUserSendTxtReqs",smsg,player)
        elseif scmd == CMDGAME.Sub_ClientToGameSvr_TableModle_PropReq then      --道具使用
            SendData(Sraw.get(player,"nRoomAddr"),"OnNetMsgUserPropReq",smsg,player)
        elseif scmd == CMDGAME.Sub_ClientToGameSvr_TableModle_GPSData then      --玩家上报GPS信息
            SendData(Sraw.get(player,"nRoomAddr"),"OnNetMsgGPSData",smsg,player)
        else
            SendData(Sraw.get(player,"nRoomAddr"), "OnGameMessage",scmd, smsg, player)
        end       
    end
end


skynet.register_protocol {
	name = "client",
	id = skynet.PTYPE_CLIENT,
    unpack = function(msg,sz) 
        return  skynet.tostring(msg,sz), sz  
    end,
	dispatch = function (_, _, smsg, sz)
		local ok, result  = pcall(request, smsg, sz)
		if ok then
			if result then
				send_package(client_fd, result)
			end
		else
			skynet.error(result)
		end
	end
}


function CMD.send_data(pack)
    local mcmd,scmd = string.unpack(">I2>I2", pack, 1) 

    if not (mcmd == 303 and scmd == 2051) then
        skynet.error("[agent]-> ", mcmd, scmd)
    end

    send_package(client_fd, pack)
end

function CMD.start(conf)
	local fd = conf.client
	local gate = conf.gate
	WATCHDOG = conf.watchdog
    local s, e = string.find(conf.clientaddr, ":")
    client_addr = string.sub(conf.clientaddr, 1, s-1) 
    playerList = conf.playerlist
    skynet.error("CMD.start gate ip="..client_addr)
    
    Self = skynet.self()
	client_fd = fd
	skynet.call(gate, "lua", "forward", fd)
end

function CMD.disconnect()
    local player = Sraw.get(playerList,tostring(playerId))
    if player then
       --  if player.nRoomAddr > 0 then
       --     SendData(Sraw.get(player,"nRoomAddr"), "OnUserNetCut",player)
       -- end
        if Self == math.floor(Sraw.get(player,"nAgentAddr")) then
            if player.nRoomAddr > 0 then
                SendData(Sraw.get(player,"nRoomAddr"), "OnUserNetCut",player)
            end
            Sraw.set(player,"nAgentAddr",0)
        end
    end
    skynet.exit()
end

skynet.start(function()
    print("agent 1 start")
	skynet.dispatch("lua", function(_,_, command, ...)
		local f = CMD[command]
		skynet.ret(skynet.pack(f(...)))
	end)
    Login = skynet.localname(".login")
    Manager = skynet.localname(".manager")
    Center_conn = skynet.localname(".center_con")
    
    math.randomseed(os.time())
end)
